// Ctrl r -> w , show white spaces

#include <SGE.h>
using namespace SGE;

#include "Bullet.h"
#include "Enemy.h"
#include "Fighter.h"

const int kMAX_BULLETS = 100;
const int kMAX_ENEMIES = 100;
const float kBULLET_SPEED = -500.0f;
const int kMAX_EXPLOSIONS = 100;

Bullet bullets[kMAX_BULLETS];
Enemy enemies[kMAX_ENEMIES];
Fighter fighter;
SGE_Emitter explosions[kMAX_EXPLOSIONS];
SGE_Sprite background;
SGE_Sound explosionSound;
SGE_Sound fireSound;

int bulletIndex(0);
int enemyIndex(0);
float spawnDelay(0.0f);
int explosionIndex(0);

bool quit = false;

void UpdateGameObjects(float deltaTime)
{
	fighter.Update(deltaTime);

	for (int i = 0; i < kMAX_BULLETS; i++)
	{
		bullets[i].Update(deltaTime);
	}

	for (int i = 0; i < kMAX_ENEMIES; i++)
	{
		enemies[i].Update(deltaTime);
	}

	for (int i = 0; i < kMAX_EXPLOSIONS; i++)
	{
		explosions[i].Update(deltaTime);
	}
}

void FireBullets()
{
	if (Input_IsKeyPressed(Keys::SPACE))
	{
		if (!bullets[bulletIndex].IsActive()) // Can do this with a longer if statement and more thought out, multiple bullets
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(0.0f, kBULLET_SPEED);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}
		if (!bullets[bulletIndex].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(-75.0f, kBULLET_SPEED);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}if (!bullets[bulletIndex].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(75.0f, kBULLET_SPEED);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}
		if (!bullets[bulletIndex].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(-150.0f, kBULLET_SPEED);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}if (!bullets[bulletIndex].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(150.0f, kBULLET_SPEED);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}
		if (!bullets[bulletIndex].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(-kBULLET_SPEED, 0.0f);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}if (!bullets[bulletIndex].IsActive())
		{
			SVector2 pos = fighter.GetPosition();
			SVector2 vel(kBULLET_SPEED, 0.0f);
			bullets[bulletIndex].Fire(pos, vel);
			fireSound.Play();

			bulletIndex = (bulletIndex + 1) % kMAX_BULLETS; // might not be efficient
		}
	}
}

void SpawnEnemies(float deltaTime)
{
	const int kWIN_WIDTH = IniFile_GetInt("WinWidth", 800); // 800 is default value, it will be used if cant find win width
	const int kWIN_HEIGHT = IniFile_GetInt("WinHeight", 600);

	spawnDelay -= deltaTime;

	if (spawnDelay <= 0)
	{
		// Spawn Enemy
		if (!enemies[enemyIndex].IsActive())
		{
			SVector2 pos((RandomFloat((kWIN_WIDTH * 0.2f), (kWIN_WIDTH * 0.8f))), -100.0f);
			enemies[enemyIndex].Spawn(pos);

			enemyIndex = (enemyIndex + 1) % kMAX_ENEMIES; // might not be efficient
		}
		
		// Reset delay time
		spawnDelay = RandomFloat(0.5f, 2.0f);
	}

	//if (Input_IsKeyDown(Keys::E))
	//{
	//	if (!enemies[enemyIndex].IsActive())
	//	{
	//		SVector2 pos(500, 0);
	//		enemies[enemyIndex].Spawn(pos);

	//		enemyIndex = (enemyIndex + 1) % kMAX_ENEMIES; // might not be efficient
	//	}
	//}
}

void CheckCollision()
{
	for (int e = 0; e < kMAX_ENEMIES; e++)
	{
		if (enemies[e].IsActive())
		{
			for (int b = 0; b < kMAX_BULLETS; b++)
			{
				if (bullets[b].IsActive())
				{
					SCircle eCircle = enemies[e].GetBoundingCircle();
					SCircle bCircle = bullets[b].GetBoundingCircle();
					/*float xDiff = eCircle.center.x - bCircle.center.x; // Can just use intersect
					float yDiff = eCircle.center.y - bCircle.center.y;
					float dist = sqrt((xDiff * xDiff) + (yDiff * yDiff));
					float radii = (eCircle.radius + bCircle.radius);*/

					if (Intersect(eCircle, bCircle))
					{
						enemies[e].Kill();
						bullets[b].Kill();

						explosions[explosionIndex].SetPosition(eCircle.center);
						explosions[explosionIndex].Start(100, true);
						explosionIndex = (explosionIndex + 1) % kMAX_EXPLOSIONS;

						explosionSound.Play();
						break;
					}

					/*if (dist <= radii)
					{
						enemies[e].Kill();
						bullets[b].Kill();
						break;
					}*/
				}
			}
		}
		
	}
}

void SGE_Initialize()
{
	const int kWIN_WIDTH = IniFile_GetInt("WinWidth", 800); // 800 is default value, it will be used if cant find win width
	const int kWIN_HEIGHT = IniFile_GetInt("WinHeight", 600);

	fighter.Load();

	SVector2 position((float)kWIN_WIDTH * 0.5f, (float)kWIN_HEIGHT - 58);

	fighter.SetPosition(position);

	for (int i = 0; i < kMAX_BULLETS; i++)
	{
		bullets[i].Load();
	}

	for (int i = 0; i < kMAX_ENEMIES; i++)
	{
		enemies[i].Load();
	}

	for (int i = 0; i < kMAX_EXPLOSIONS; i++)
	{
		explosions[i].Load("explosion.txt"); // Load an emiter, give it a texture
	}

	background.Load("space.jpg");

	explosionSound.Load("explosion.wav");
	fireSound.Load("photongun1.wav");
}

void SGE_Terminate()
{
	fighter.Unload();

	for (int i = 0; i < kMAX_BULLETS; i++)
	{
		bullets[i].Unload();
	}

	for (int i = 0; i < kMAX_ENEMIES; i++)
	{
		enemies[i].Unload();
	}

	for (int i = 0; i < kMAX_EXPLOSIONS; i++)
	{
		explosions[i].Unload();
	}

	background.Unload();
	explosionSound.Unload();
	fireSound.Unload();
}

bool SGE_Update(float deltaTime) // bool says when to quit, 
{
	UpdateGameObjects(deltaTime);
	
	FireBullets(); // Easy to read eh...

	SpawnEnemies(deltaTime);

	CheckCollision();

	if (Input_IsKeyPressed(Keys::ESCAPE))
	{
		quit = true; // To exit
	}

	return quit;
}

void SGE_Render()
{
	background.Render();

	for (int i = 0; i < kMAX_ENEMIES; i++)
	{
		enemies[i].Render();
	}

	for (int i = 0; i < kMAX_BULLETS; i++)
	{
		bullets[i].Render();
	}

	fighter.Render();

	for (int i = 0; i < kMAX_EXPLOSIONS; i++)
	{
		explosions[i].Render(true);
	}
}